﻿using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

// http://forums.lhotka.net/forums/p/9786/45971.aspx

// Original Silverlight 4 ComboBox does not show SelectedValue in design mode.
// After reloading an entity list, ComboBox becomes empty 

namespace Riba.Tools.Controls
{
	public class ComboBoxEx : ComboBox
	{
		private bool _suppressSelectionChangedUpdatesRebind;

		public static readonly DependencyProperty SelectedValueProperProperty = DependencyProperty.Register(
			"SelectedValueProper",
			typeof(object),
			typeof(ComboBoxEx),
			new PropertyMetadata
				(
					(o, dp) =>
					{
						var comboBoxEx = o as ComboBoxEx;
						if (comboBoxEx == null)
							return;

						comboBoxEx.SetSelectedValueSuppressingChangeEventProcessing(dp.NewValue);
					}
				)
			);

		[Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
		public object SelectedValueProper
		{
			get { return GetValue(SelectedValueProperProperty); }
			set { SetValue(SelectedValueProperProperty, value); }
		}

		public ComboBoxEx()
		{
			SelectionChanged += ComboBoxEx_SelectionChanged;
		}

		// Updates the current selected item when the collection has changed.
		protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
		{
			// Must re-apply value here because the combobox has a bug that
			// despite the fact that the binding still exists, it doesn't
			// re-evaluate and subsequently drops the binding on the change event
			SetSelectedValueSuppressingChangeEventProcessing(SelectedValueProper);
		}

		private void ComboBoxEx_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			// Avoid recursive stack overflow
			if (_suppressSelectionChangedUpdatesRebind)
				return;

			if (e.AddedItems != null && e.AddedItems.Count > 0)
			{
				//SelectedValueProper = GetMemberValue( e.AddedItems[0] );      
				SelectedValueProper = SelectedValue;
				// This is faster than GetMemberValue
			}

			// Do not apply the value if no items are selected (ie. the else) 
			// because that just passes on the null-value bug from the combobox
		}

		//  Gets the member value based on the Selected Value Path
		//private object GetMemberValue(object item)
		//{
		//  return item.GetType().GetProperty(SelectedValuePath).GetValue(item, null);
		//}

		// Sets the selected value suppressing change event processing.  
		private void SetSelectedValueSuppressingChangeEventProcessing(object newSelectedValue)
		{
			try
			{
				_suppressSelectionChangedUpdatesRebind = true;
				SelectedValue = newSelectedValue;
			}
			finally
			{
				_suppressSelectionChangedUpdatesRebind = false;
			}
		}
	}
}
